package com.cafe.pro.aop;
import com.cafe.pro.util.CryptoUtils;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;


/**
 * 统一加密处理
 *
 * @author cafe
 * @version 1.0
 * @since 2025-06-08 17:00:00
 */
@Slf4j
@ControllerAdvice
public class CryptoResponseAdvice implements ResponseBodyAdvice<Object> {

    private static final String HEADER_ENCRYPT_OPTION = "X-Content-Encrypted";
    private static final String HEADER_AUTHORIZATION = "Authorization";

    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
        // 检查方法或类上是否有@EncryptResponse注解
        return returnType.hasMethodAnnotation(CryptoResponse.class) ||
                returnType.getDeclaringClass().isAnnotationPresent(CryptoResponse.class);
    }

    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType,
                                  MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType,
                                  ServerHttpRequest request, ServerHttpResponse response) {

        // 获取当前请求的HttpServletRequest
        HttpServletRequest httpServletRequest = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();

        String url = request.getURI().toString();
        log.info("url:{}，响应内容加密返回", url);

        // 获取请求头中的token，格式为：4e079bb4-b5c3-4cae-8cdd-8101cd511dc2
        String thirdSessionHeader = httpServletRequest.getHeader(HEADER_AUTHORIZATION);
        String aesKey = CryptoUtils.extractAesKey(thirdSessionHeader);
        log.debug("提取key:{}", aesKey);
        if (StringUtils.isEmpty(aesKey)) {
            throw new RuntimeException("当前用户未登录");
        }
        try {
            // 将对象转为JSON字符串
            ObjectMapper objectMapper  = new ObjectMapper();
            objectMapper.registerModule(new JavaTimeModule());
            String strBody = objectMapper.writeValueAsString(body);
            // AES加密并返回加密后的字符串
            String encryptedBody = CryptoUtils.aesEncrypt(strBody, aesKey);

            // 添加 crypto-option 响应头
            response.getHeaders().add(HEADER_ENCRYPT_OPTION, "1");
            return encryptedBody;
        } catch (Exception e) {
            throw new RuntimeException("加密响应数据失败", e);
        }
    }
}